package com.wiscamp.ninechapters.panels.infrastructure.repositories;


import com.wiscamp.ninechapters.panels.domain.entities.Organization;
import com.wiscamp.ninechapters.panels.domain.repositories.OrganizationRepository;
import com.wiscamp.ninechapters.panels.infrastructure.converters.OrganizationConverter;
import com.wiscamp.ninechapters.panels.infrastructure.mappers.OrganizationMapper;
import com.wiscamp.ninechapters.panels.infrastructure.mappers.OrganizationViewMapper;
import com.wiscamp.ninechapters.panels.infrastructure.po.OrganizationPO;
import com.wiscamp.ninechapters.panels.infrastructure.views.OrganizationView;
import cube.ddd.aspect.HandleDataException;
import cube.ddd.common.query.PagedObjects;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.utils.PersistenceUtils;
import org.springframework.stereotype.Repository;

import java.util.Collection;

@Repository
public class OrganizationRepositoryImpl implements OrganizationRepository {

    private final OrganizationMapper organizationMapper;

    private final OrganizationViewMapper organizationViewMapper;

    public OrganizationRepositoryImpl(OrganizationMapper organizationMapper, OrganizationViewMapper organizationViewMapper) {
        this.organizationMapper = organizationMapper;
        this.organizationViewMapper = organizationViewMapper;
    }

    private OrganizationPO getOrganizationPO(long organizationId) {
        return PersistenceUtils.findById(organizationId, organizationMapper::findById);
    }

    @HandleDataException
    public Organization getOrganization(long organizationId) {
        return PersistenceUtils.findEntityById(organizationId, organizationViewMapper::findById,
                OrganizationConverter.Instance::toOrganizationByView);

    }

    @HandleDataException
    public Organization getOrganizationByCode(String organizationCode) {
        return PersistenceUtils.getEntityByText(organizationCode, organizationViewMapper::findByOrganizationCode,
                OrganizationConverter.Instance::toOrganizationByView);
    }

    @HandleDataException
    public Collection<Organization> getOrganizationsByIds(Collection<Long> organizationIds) {
        return PersistenceUtils.getEntitiesByIds(organizationIds, organizationViewMapper::findAllById,
                OrganizationConverter.Instance::toOrganizationByView);
    }

    @HandleDataException
    public Collection<Organization> getAvailableOrganizations() {
        return PersistenceUtils.getEntities(organizationViewMapper::findListByAvailable,
                OrganizationConverter.Instance::toOrganizationByView);
    }

    @HandleDataException
    public Organization getOrganizationByName(String organizationName) {
        return PersistenceUtils.getEntityByText(organizationName, organizationViewMapper::findByOrganizationName,
                OrganizationConverter.Instance::toOrganizationByView);
    }

    @HandleDataException
    public PagedObjects<Organization> getOrganizationsByQuery(PagedQuery query) {
        PagedObjects<OrganizationView> pagedObjects = PersistenceUtils.getPersistenceObjectsByQuery(query, organizationViewMapper::findAll);
        return PersistenceUtils.convertPagedObjects(pagedObjects, OrganizationConverter.Instance::toOrganizationByView);
    }

    @HandleDataException
    public Organization saveOrganization(Organization organization) {
        if (organization.getOrganizationId() <= 0) {
            return PersistenceUtils.createEntity(organization, organizationMapper::saveAndFlush,
                    OrganizationConverter.Instance::toOrganizationPO, OrganizationConverter.Instance::toOrganization);
        } else {
            var existedPO = getOrganizationPO(organization.getOrganizationId());
            if (existedPO == null) existedPO = new OrganizationPO();
            return PersistenceUtils.updateEntity(organization, existedPO, organizationMapper::saveAndFlush,
                    OrganizationConverter.Instance::toOrganizationPO, OrganizationConverter.Instance::toOrganization);
        }
    }
}
